package maze.net.client;

import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;

import maze.events.EventDispatcher;
import maze.model.Player;
import maze.net.MessageType;
import maze.net.SGMPEvent;
import maze.net.SGMPInputStream;
import maze.net.SGMPOutputStream;
import maze.pojo.Action;
import maze.utils.Async;

public class SGMPClient extends EventDispatcher {
	private boolean running = false;
	private Socket socket;
	private SGMPInputStream in;
	private SGMPOutputStream out;

	public SGMPClient(Socket socket) {
		super();
		this.socket = socket;
	}

	public void sendACK() {
		// System.out.println("sendACK");
		try {
			out.send(MessageType.C_ACK);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void sendAction(Action action) {
		try {
			out.send(MessageType.C_Action, (byte) action.bit);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void start() {
		Async.execute(new Runnable() {
			@Override
			public void run() {
				try {
					in = new SGMPInputStream(socket.getInputStream());
					out = new SGMPOutputStream(socket.getOutputStream());
					for (;;) {
						if (!running) {
							try {
								wait();
							} catch (InterruptedException e) {
							}
						}
						read();
					}
				} catch (EOFException e) {
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		});
	}

	public synchronized void pause() {
		running = false;
	}

	public synchronized void resume() {
		running = true;
		notifyAll();
	}

	private void read() throws IOException {
		MessageType type = in.readHeader();
		byte action;
		switch (type) {
		case S_PlayerReady:
			int playerId = in.readByte();
			Player.setSelfId(playerId);
			dispatchEvent(new SGMPEvent(type));
			break;
		case S_Countdown:
			long seed = in.readLong();
			dispatchEvent(new SGMPCountdownEvent(type, seed));
			break;
		case S_Win:
		case S_Draw:
		case S_Lose:
			action = in.readByte();
			dispatchEvent(new SGMPResultEvent(type,
					Action.getAction((action & 0xF0) >> 4),
					Action.getAction(action & 0x0F)));
			break;
		case S_Action:
			action = in.readByte();
			if (action != 0) {
				System.out.println(Integer.toHexString(action));
				System.out.println("" + Action.getAction((action >> 4) & 0x0F)
						+ Action.getAction(action & 0x0F));
			}
			dispatchEvent(new SGMPActionEvent(type,
					Action.getAction((action >> 4) & 0x0F),
					Action.getAction(action & 0x0F)));
			break;
		}
	}
}
